package org.jeecg.trace.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.trace.dto.MaterialHistoryDTO;
import org.jeecg.trace.dto.ProductionTraceDTO;
import org.jeecg.trace.mapper.ProductionTraceMapper;
import org.jeecg.trace.service.ProductionTraceService;
import org.jeecgframework.poi.excel.ExcelExportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@Slf4j
public class ProductionTraceServiceImpl implements ProductionTraceService {
    @Autowired
    private ProductionTraceMapper productionTraceMapper;

    private ThreadPoolExecutor fastTriggerPool = null;

    private final int PAGE_NUM = 50000;

    /**
     * 阻塞队列获取数据超时时间
     */
    private static final Integer PAGE_SEARCH_TIMEOUT_SECONDS = 60;

    @Override
    public IPage<ProductionTraceDTO> queryList(Page<ProductionTraceDTO> page, Map<String, String> map) {
        List<String> descriptions = new ArrayList<>();
        if (map.containsKey("recId")) {
            descriptions = Arrays.asList(map.get("recId").split(","));
        }
        return productionTraceMapper.queryList(page, map, descriptions);
    }

    @Override
    public void exportXls(HttpServletRequest request, HttpServletResponse response, Map<String, String> map) {
        log.info("sql分页导出excel....");
        long start = System.currentTimeMillis();
        //定义easyExcel导出的对象
        ExcelWriter excelWriter = null;
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=demo.xls");
        //内容样式策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        //垂直居中,水平居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);


        // 字体策略
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
        contentWriteFont.setFontHeightInPoints((short) 8);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        //头策略使用默认 设置字体大小
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 10);
        headWriteCellStyle.setWriteFont(headWriteFont);
        ExcelWriterSheetBuilder writeSheet = EasyExcel.writerSheet("生产追溯导出");
        writeSheet.head(ProductionTraceDTO.class)
                .registerWriteHandler(new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle));
        try {
            //查询条件
            //获取总数
            List<String> recIds = new ArrayList<>();
            if (map.containsKey("recId")) {
                recIds = Arrays.asList(map.get("recId").split(","));
            }
            //long count = productionTraceMapper.countAll(map, recIds);
            //计算开启的线程数
            //int loopNum = new Double(Math.ceil((double) count / PAGE_NUM)).intValue();
            //log.info("多线程查询，总数：{}，开启线程数：{}", count, loopNum);
            //队列存放数据库中查询导的数据
            //ArrayBlockingQueue<List<ProductionTraceDTO>> queue = new ArrayBlockingQueue<>(loopNum, true);
            //当数据为空时跳出写入循环
            //AtomicInteger atomicInteger = new AtomicInteger(loopNum);
            //并发查询数据
            //executeTask(queue, loopNum, count, map, recIds);
            Page<ProductionTraceDTO> page = new Page<>(1,1000000);
            List<ProductionTraceDTO> list = productionTraceMapper.queryList(page, map, recIds).getRecords();
            excelWriter = EasyExcel.write(response.getOutputStream(), ProductionTraceDTO.class)
                    .build();
            //list = queue.poll(PAGE_SEARCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
            excelWriter.write(list, writeSheet.build());
            //读写分离式写入
//            while (list != null) {
//                excelWriter.write(list, writeSheet);
//                //跳出循环
//                if (0 == atomicInteger.decrementAndGet()) {
//                    break;
//                }
//            }
            long end = System.currentTimeMillis();
            log.info("导出耗时：" + (end - start));
        } catch (Exception e) {
            log.debug("文件导出报错，{}", e.getMessage());
        } finally {
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }


    /**
     * 并发查询数据库
     *
     * @param queue   存放数据队列
     * @param loopNum 查询次数
     * @param count   总数
     */
    private void executeTask(ArrayBlockingQueue<List<ProductionTraceDTO>> queue, int loopNum, long count, Map<String, String> map, List<String> recIds) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(loopNum);
        // 创建Future列表
        List<Future<List<ProductionTraceDTO>>> futures = new ArrayList<>();

        //loopNum并发查询次数
        for (int i = 0; i < loopNum; i++) {
            Page<ProductionTraceDTO> page = new Page<>();
            page.setCurrent((long) i * PAGE_NUM);
            if (i == loopNum - 1) {
                page.setSize(count - (long) PAGE_NUM * i);
            } else {
                page.setSize(PAGE_NUM);
            }
            Future<List<ProductionTraceDTO>> future = executorService.submit(() -> {
                IPage<ProductionTraceDTO> productionTraceDTOIPage = productionTraceMapper.queryList(page, map, recIds);
                log.info("开始查询{}", productionTraceDTOIPage.getRecords().size());
                List<ProductionTraceDTO> caseInfos = productionTraceDTOIPage.getRecords();
                return caseInfos;
            });
            futures.add(future);
            log.info("开始查询第{}条开始的{}条记录", i * PAGE_NUM, PAGE_NUM);
        }
        for (Future<List<ProductionTraceDTO>> future : futures) {
            queue.put(future.get());
        }
        // 关闭线程池
        executorService.shutdown();
    }
}
